﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PostSharp.Extensibility;
using PostSharp.Laos;

namespace CyclicReferences.Public
{
    /// <summary>
    /// applied to a class, will create a nested class with a copy of all the 
    /// fields and properties adorned with the datamember attribute. Will also create 'original' value
    /// holders. Creates a ctor that accepts the original type and copies all the values from it,
    /// using the correct approach to find the 'loaded' / 'original' value.
    /// Will create a deserialize method in the original type that is able to copy all values
    /// from the surrogate to itself.
    /// </summary>
    [Serializable]
    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    [MulticastAttributeUsage(MulticastTargets.Class, AllowMultiple = false)]
    public class CreateSerializeSurrogateAttribute : LaosAspect, ILaosTypeLevelAspect
    {
        public string OriginalValueProvider { get { return originalValueProvider; } }

        string originalValueProvider;

        public CreateSerializeSurrogateAttribute(string OriginalValueProvider)
        {
            this.originalValueProvider = OriginalValueProvider;
        }

        #region ILaosTypeLevelAspect Members

        /// <summary>
        /// Method called at compile-time by the weaver just before the instance is serialized.
        /// </summary>
        /// <param name="type">Type on which this instance is applied.</param>
        /// <remarks>
        /// 	<para>Derived classes should implement this method if they want to compute some information
        /// at compile time. This information to be stored in member variables. It shall be
        /// serialized at compile time and deserialized at runtime.
        /// </para>
        /// 	<para>
        /// You cannot store and serialize the <paramref name="type"/> parameter because it is basically
        /// a runtime object. You shall receive the <see cref="T:System.Type"/> at runtime by the
        /// <see cref="M:PostSharp.Laos.ILaosTypeLevelAspect.RuntimeInitialize(System.Type)"/> method.
        /// </para>
        /// </remarks>
        public void CompileTimeInitialize(Type type)
        {
                        
        }

        /// <summary>
        /// Method called at compile-time by the weaver to validate the application of this
        /// custom attribute on a specific type.
        /// </summary>
        /// <param name="type">Type on which this instance is applied.</param>
        /// <returns>
        /// 	<b>true</b> if the aspect should be applied to that <paramref name="type"/>,
        /// <b>false</b> otherwise.
        /// </returns>
        /// <remarks>Returning <b>false</b> does not emit an error. You should use
        /// a <see cref="T:PostSharp.Extensibility.MessageSource"/> to emit errors. This method can be used to filter
        /// out types that do not need to be modified.</remarks>
        public bool CompileTimeValidate(Type type)
        {
            return true;
        }

        /// <summary>
        /// Method called at runtime just after the instance is deserialized.
        /// </summary>
        /// <param name="type">Type on which this instance is applied.</param>
        public void RuntimeInitialize(Type type)
        {
        }

        #endregion

        #region ILaosWeavableAspect Members

        /// <summary>
        /// Gets the weaving priority of the aspect.
        /// </summary>
        /// <value></value>
        public int AspectPriority
        {
            get { return int.MaxValue; }
        }

        #endregion

    }
}
